/* Turska Framework/UI library (Turs2)
 * Copyright 2003-2010 Jetro Lauha
 * All rights reserved.
 * Web: http://iki.fi/jetro/turska/
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of EITHER:
 *   (1) The GNU Lesser General Public License as published by the Free
 *       Software Foundation; either version 2.1 of the License, or (at
 *       your option) any later version. The text of the GNU Lesser
 *       General Public License is included with this library in the
 *       file LICENSE-LGPL.txt.
 *   (2) The BSD-style license that is included with this library in
 *       the file LICENSE-BSD.txt.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
 * LICENSE-LGPL.txt and LICENSE-BSD.txt for more details.
 *
 * $Id: T2VerticalStripBitmapFontIrr.cpp 157 2010-01-01 23:31:43Z jlauha $
 * $Revision: 157 $
 */

#include "Turs2.h"

#ifdef T2_USE_IRR

#include <assert.h>
#include "irrlicht.h"

using namespace irr;

namespace turska
{


VerticalStripBitmapFontIrr::VerticalStripBitmapFontIrr(GraphicsIrr *graphics,
                                                       const C8 *fileName,
                                                       const C8 *fontString,
                                                       UI8 alphaTraceMinAlpha) :
    VerticalStripBitmapFont(static_cast<Graphics *>(graphics), fileName, fontString, alphaTraceMinAlpha)
{
}


VerticalStripBitmapFontIrr::~VerticalStripBitmapFontIrr()
{
}


bool VerticalStripBitmapFontIrr::reload()
{
    video::IImage *image;
    UI32 g, x, y, x1, x2;

    if (mLoaded && mGlyphs != 0)
    {
        UI32 a;
        for (a = 0; a < mGlyphCount; ++a)
            delete mGlyphs[a];
        delete[] mGlyphs;
        mGlyphs = 0;
        mGlyphCount = 0;
    }
    mLoaded = false;

    GraphicsIrr *graphicsIrr = static_cast<GraphicsIrr *>(mGraphics);
    image = graphicsIrr->loadIrrImage(mFileName);
    if (image == 0)
        return false;

    const s32 imageWidth = image->getDimension().Width;
    const s32 imageHeight = image->getDimension().Height;
    mGlyphCount = imageHeight / imageWidth;
    if (mGlyphCount < 1)
    {
        image->drop();
        return false;
    }

    mFontHeight = imageWidth;

    u32 bytesPerPixel = image->getBytesPerPixel();
    bool useGetPixel = false;
    const u32 alphaMask = image->getAlphaMask();
    video::ECOLOR_FORMAT ecf = image->getColorFormat();
    if (ecf == video::ECF_R8G8B8)
        useGetPixel = true;

    void *pixels = 0;
    if (!useGetPixel)
    {
        pixels = image->lock();
        if (pixels == 0)
            useGetPixel = true;
    }

    mGlyphs = new Image *[mGlyphCount];
    const u32 pitch = image->getPitch();

    for (g = 0; g < mGlyphCount; ++g)
    {
        I32 w, h;
        x1 = imageWidth;
        x2 = 0;
        for (x = 0; (s32)x < imageWidth; ++x)
        {
            for (y = g * imageWidth; y < (g + 1) * imageWidth; ++y)
            {
                UI32 pixel;
                UI8 red, green, blue, alpha = 0;
                UI8 traceMinAlpha = mAlphaTraceMinAlpha;
                if (useGetPixel)
                {
                    irr::video::SColor pixel = image->getPixel(x, y);
                    red = (UI8)pixel.getRed();
                    green = (UI8)pixel.getGreen();
                    blue = (UI8)pixel.getBlue();
                    alpha = (UI8)pixel.getAlpha();
                }
                else
                {
                    switch (ecf)
                    {
                    case video::ECF_A1R5G5B5:
                        pixel = (UI32)*(UI16 *)((UI8 *)pixels + y * pitch + x * bytesPerPixel);
                        alpha = ((pixel >> 15) & 1) * (traceMinAlpha + 1);
                        red = (pixel >> 10) & 0x1f;
                        green = (pixel >> 5) & 0x1f;
                        blue = pixel & 0x1f;
                        break;
                    case video::ECF_R5G6B5:
                        alpha = 0;
                        red = (pixel >> 11) & 0x1f;
                        green = (pixel >> 5) & 0x3f;
                        blue = pixel & 0x1f;
                        break;
                    case video::ECF_A8R8G8B8:
                        pixel = *(UI32 *)((UI8 *)pixels + y * pitch + x * bytesPerPixel);
                        alpha = (pixel >> 24) & 0xff;
                        red = (pixel >> 16) & 0xff;
                        green = (pixel >> 8) & 0xff;
                        blue = pixel & 0xff;
                        break;
                    }
                }
                if (alphaMask == 0)
                {
                    // TODO: Better handling of alpha when image doesn't have it.
                    alpha = red | green | blue;
                    traceMinAlpha = 0;
                }
                // trace right edge
                if (alpha > traceMinAlpha && x > x2)
                    x2 = x;
                // trace left edge
                if (alpha > traceMinAlpha && x < x1)
                    x1 = x;
            }
        }
        if (x1 > x2)
        {
            w = imageWidth / 3;
            h = imageWidth;
            x1 = 0;
            x2 = w;
        }
        else
        {
            w = x2 - x1 + 1;
            h = imageWidth;
        }

        PixelRectangle area;
        area.x = x1;
        area.y = g * imageWidth;
        area.width = w;
        area.height = h;
        
        // Convert the image into an OpenGL texture.
        // TODO - allow usage of nearest neighbor sampled fonts? -> API change..
        C8 nameBuf[MAX_FILENAME_LENGTH + 15];
        snprintf(nameBuf, MAX_FILENAME_LENGTH + 15, "%d_%s", g, mFileName);
        mGlyphs[g] = graphicsIrr->createImage(nameBuf, image, false, IF_FILTER_LINEAR, &area);
    }

    if (!useGetPixel)
        image->unlock();

    // We don't need the original image anymore
    image->drop();

    mLoaded = true;
    return mLoaded;
}


} // namespace turska
#endif // T2_USE_IRR
